;;########################################################################
;; mdsmob2.lsp Multidimensional Scaling, Part 2
;; this file contains visualization and create data code
;; Copyright (c) 1991, 92 by Mary M. McFarlane
;; Written   by Mary McFarlane & Chris Wiesen, September, 1991
;; Rewritten by Mary McFarlane, February, 1992
;;########################################################################

(defmeth cmds-model :visualize ()
  (if (not (eq current-object self)) (setcm self))
  (let* ((spread (spread-plot 
                  (matrix '(2 3) 
                          (list (send self :mds-3d-scatterplot)
                                (send self :mds-3d-spin-plot)
                                (send self :name-plot)
                                (send self :mds-2d-plot)
                                (send self :scree-plot)
                                (send self :mds-stress-plot)
                                ))))
         )
    (mapcar #'(lambda (plot) (send plot :linked t)) (select (send spread :all-plots) (list 0 1 2 3)))
    (send spread :show-spreadplot)
    
    (defmeth spread :spreadplot-help ()
      (plot-help-window (strcat "SpreadPlot Help"))
      (paste-plot-help (format nil "This is the SpreadPlot for Multidimensional Scaling. In this SpreadPlot the windows are linked by the data's stimuli (rows and columns of the data matrix) and by the dimensions of the MDS model. They are also linked via the equations of the MDS model.~2%"))
      (paste-plot-help (format nil "The Scatterplot Matrix window, which is in the upper left corner, lets you choose which MDS dimensions are displayed in other windows. You can select two dimensions by clicking on an off-diagonal cell. You can also select several dimensions by shift-clicking on several cells.~2%"))
(paste-plot-help (format nil "The Stimuli window, at the upper right, presents labels for the stimuli (the rows and columns of the data matrix). Selecting labels will cause points and vectors in the other plots to be highlighted.~2%"))
      (paste-plot-help (format nil
"The points in the windows of this spreadplot are linked together. When you brush or click on them in one window, the corresponding points or vectors in other windows are also highlighted. The points are linked together because they represent the same row and column of your data. By looking for the structure revealed in each window you can get a better understanding of your data.~2%"))
      (paste-plot-help (format nil "The windows are also linked algebraically through the Drag Point mouse mode of the Stimulus Plane window. When the mouse is in this mode, points can be moved to new locations. When a point is moved, the model recalculates itself and presents the new results graphically.~2%"))
      (show-plot-help)
     ;(call-next-method :skip)
      t)))
   

(defmeth cmds-model :mds-stress-plot (&optional (stream t))
  (let ((num-dims (send self :number-dimensions))
        (num-mats (length (send self :matrices-numbers)))
        )
  (if (not (eq current-object self)) (setcm self))
  (setf stressp (plot-points (list 1) 
                             (list (send self :stress))
                             :show nil
                             :title "Stress Plot"
                             :variable-labels (list "Iteration" "Stress")))
  (send stressp :margin 0 17 0 0)
  (send stressp :add-overlay (send vista-graph-overlay-proto 
                :new :mouse-mode nil :new-x nil :new-y nil))
  (send stressp :showing-labels t)
  (send stressp :point-label 0 
        (format nil "~5,4f" (send stressp :point-coordinate 1 0)))
  (send stressp :point-state 0 'selected)
  (send stressp :use-color t)
  (send stressp :point-color 0 'red)
  (send stressp :mouse-mode 'brushing)
  (send stressp :range 0 0 5)
  (send stressp :x-axis t t 6)
  (send stressp :menu nil)
    (send stressp :legend2 "Stress Plot")
  (defmeth stressp :redraw ()
    (let* ((maxy (max (send stressp :point-coordinate 1 
                            (iseq (send stressp :num-points)))))
           (gnrx nil)
           )
      (when (> (send self :num-points) (second (send self :range 0)))
            (setf gnrx 
                  (get-nice-range 0 (+ 5 (second (send self :range 0))) 5))
            (send self :range 0 (first gnrx) (second gnrx) :draw nil)
            (send self :x-axis t t (third gnrx) :draw nil))
      (send stressp :range 1 0  (* .1 (ceiling (* 10 maxy))) :draw nil)
      (send stressp :y-axis t t (1+   (ceiling (* 10 maxy))) :draw nil)
      (call-next-method)))

(defmeth stressp :add-lines-with-points (&key (color 'black))
  (let* ((ps (send self :num-points)))
    (send self :clear-lines :draw nil)
    (send self :add-lines (send self :point-coordinate 0 (iseq ps))
          (send self :point-coordinate 1 (iseq ps)) :color color)
    (send self :redraw)))

(defmeth stressp :plot-help ()
      (plot-help-window (strcat "Help for " (send self :title)))
      (paste-plot-help (format nil "The Stress plot shows the fit of the multidimensional scaling model to the dissimilarity data."))
    (when (> num-mats 1)
          (paste-plot-help (format nil " Since there are ~d matrices of data, the fit is to the root-mean-squared data matrix."num-mats)))
    (paste-plot-help (format nil " The fit is shown for a ~d-dimensional model, since this is the dimensionality you specified. The fit is shown for each iteration. Initially, there is just one value shown.~2%" num-dims))

(if (= 1 (send stressp :num-points))
    (paste-plot-help (format nil "Currently, the fit is shown for just the initial solution. You can start the iterative process by clicking on the ITERATE button in the STIMULUS SPACE window~2%"))
    (paste-plot-help (format nil "Currently, the fit is shown for ~d iterations. Additional iterations can be performed by clicking on the ITER button in the STIMULUS SPACE window.~2%"(send stressp :num-points))))

    (paste-plot-help (format nil "The Stress plot is used to help you decide whether more iterations are needed to obtain a stable solution. As the iterations proceed, the positions of the stimulus points, as shown in the STIMULUS PLANE MATRIX, STIMULUS SPACE and STIMULUS PLANE plots, become stable, and the Stress value declines slowly, if at all. When this happens, the iterative process has converged on a stable solution, which is ready for interpretation.~2%"))
    (paste-plot-help (format nil "Unfortunately, it is not possible to say what value of Stress represents a good fit. It is known that Stress is effected artifactually by the number of stimuli and the number of dimensions, making it essentially impossible to say whether a particular value is good or bad. You must rely instead on whether the stimulus space, as shown in the STIMULUS PLANE MATRIX, STIMULUS SPACE and STIMULUS PLANE plots, is interpretable."))
      (show-plot-help))

  stressp))

(defmeth cmds-model :mds-2d-plot (&optional (stream t))
  (if (not (eq current-object self)) (setcm self))
  (setf *mds* self)
  (setf pp (plot-points (col (send self :xmatrix) 
                             (iseq (send self :number-dimensions)))
               :show nil 
               :scale-type 'fixed
               :title "Stimulus Plane"
               :variable-labels (list "Dimension 1" "Dimension 2" 
                     "Dimension 3" "Dimension 4" "Dimension 5" "Dimension 6" 
                     "Dimension 7" "Dimension 8" "Dimension 9")
               :point-labels (send self :stimulus-names)))
  (send pp :point-symbol (iseq (send pp :num-points)) 'square)
  (send pp :use-color t)
  (send pp :point-color (iseq (send pp :num-points)) 'blue)
  (send pp :showing-labels t)
  (send pp :linked t)
  (send pp :margin 0 17 0 0)
  (send pp :add-overlay (send vista-graph-overlay-proto 
                                       :new :new-x nil :new-y nil :undo t))
 
  (send pp :add-mouse-mode 'point-moving
      :title "Drag Point"
      :cursor 'finger
        :click :do-point-moving)

 (send pp :mouse-mode 'brushing)
 ; (send pp :delete-mouse-mode 'selecting);PV It does not work

  (send pp :adjust-to-data)
  (setf minppxy (min (combine (col (send self :xmatrix) 
                                   (iseq (send self :number-dimensions))))))
  (setf maxppxy (max (combine (col (send self :xmatrix) 
                                   (iseq (send self :number-dimensions))))))
  (setf gnrpp (get-nice-range minppxy maxppxy 5))
  (send pp :range 0 (first gnrpp) (second gnrpp) :draw nil)
  (send pp :range 1 (first gnrpp) (second gnrpp) :draw nil)
  (send pp :x-axis t t (third gnrpp) :draw nil)
  (send pp :y-axis t t (third gnrpp) :draw nil)
  (send pp :legend2 "Stimulus Plane")

  (defmeth pp :do-point-moving (x y a b)
    (let* ((pti      (send self :drag-point x y))
           (xvaryvar (send self :content-variables))
           (xvar     (first  xvaryvar))
           (yvar     (second xvaryvar))
           (x nil)
           (y nil))
      (when pti
            (setf x (send self :point-coordinate xvar pti))   
            (setf y (send self :point-coordinate yvar pti))
            (send current-object :use-new-point pti xvar yvar x y))))

  (defmeth pp :undo-graph-change (m1 m2)
    (cond
      (m1 (send *mds* :back-to-start))
      (t  (send *mds* :back-just-one)))
    )

;next two were scatterplot-proto methods

(defmeth pp :add-lines-with-points (&key (color 'black))
  (let* ((ps (send self :num-points)))
    (send self :clear-lines :draw nil)
    (send self :add-lines (send self :point-coordinate 0 (iseq ps))
          (send self :point-coordinate 1 (iseq ps)) :color color)
    (send self :redraw)))
         
(defmeth pp :do-nothing (x y m1 m2)
  (let* ((xscore (select (send self :canvas-to-real x y) 0))
         (yscore (select (send self :canvas-to-real x y) 1))
         (xvar (select (send pp :current-variables) 0))
         (yvar (select (send pp :current-variables) 1))
         (i (send pp :points-selected)))
   (when (or (> (length i) 1)
            (< (length i) 1))
        (message-dialog "You must select exactly 1 point to be relocated"))
    (when (= (length i) 1)
       (send current-model :use-new-point i xvar yvar xscore yscore))))

  (defmeth pp :plot-help ()
    (plot-help-window (strcat "Help for " (send self :title)))
    (paste-plot-help (format nil "The STIMULUS PLANE plot is a scatterplot that shows a 2-dimensional view of the MDS stimulus space.~2%"))
    (paste-plot-help (format nil "The plot is like other scatterplots, except it has a special mouse mode which is designed to help you guide the iterative process. In addition, the plot has an UNDO button to undo the changes you make to the iterative process.~2%"))
    (paste-plot-help (format nil "DRAG POINT~%The MOUSE button can be used to obtain a dialog box presenting the selection of mouse modes. The DRAG POINT mouse mode allows you to drag individual points to new locations in the plot. Simply locate your cursor (a pointing finger) on a point, and drag it to a new location. Each time you do this, ViSta will display the point's new postion in the STIMULUS PLANE MATRIX and STIMULUS SPACE windows, and will recalculate and display the new Stress value in the STRESS window.~2%"))
    (paste-plot-help (format nil "UNDO BUTTON~%The UNDO button can be used to undo the changes created by the DRAG POINT mouse mode. If you click on the button, the last point-move is undone. A shift-click undoes all changes and returns the space to its initial state.~2%"))  
    (show-plot-help))
  pp)





(defmeth cmds-model :mds-3d-scatterplot (&optional (stream t))
  (setf sm (scatterplot-matrix (col (send self :xmatrix) (iseq (send self :number-dimensions)))
                               :show nil
                      :title "Stimulus Plane Matrix"
                      :variable-labels (list "Dim1" "Dim2" 
                        "Dim3" "Dim4" "Dim5" "Dim6" "Dim7" "Dim8" "Dim9")                          
                      :point-labels (send self :stimulus-names)
                      ))
  (send sm :linked t)
  (send sm :point-symbol (iseq (send sm :num-points)) 'square)
  (send sm :use-color t)
  (send sm :point-color (iseq (send sm :num-points)) 'blue)
  (send sm :margin 0 17 0 0)
  (send sm :add-overlay (send vista-graph-overlay-proto 
                                       :new :new-x nil :new-y nil))
  (send sm :adjust-to-data)

  (defmeth sm :do-variable-focus (x y m1 m2)
"Method to focus on variable subplots modified to work for mds-model. Assumes that two other plots exist.  These plots MUST be named pp (the scatterplot) and sp (the spin-plot).  A click on a subplot sends it to scatterplot.  Two or three shift-clicks send first three selected variables to spin-plot and first two to scatterplot."
    (let ((cur-var (send self :current-variables))
          )
      (when (not m1)
            (when (/= (select cur-var 0) (select cur-var 1))
                  (send pp :current-variables 
                        (select cur-var 0) (select cur-var 1) )
                  (send pp :range (select cur-var 0) (first gnrpp) (second gnrpp) :draw nil)
                  (send pp :range (select cur-var 1) (first gnrpp) (second gnrpp) :draw nil)
                  (send pp :x-axis t t (third gnrpp) :draw nil)
                  (send pp :y-axis t t (third gnrpp) :draw t)
                  )
            (setf spin-var ())
            )
      (when m1
            (when (= (select cur-var 0) (select cur-var 1))
                  (setf cur-var (list (select cur-var 0))))
            (when (< (length spin-var) 3)
                  (setf spin-var (adjoin (select cur-var 0) spin-var))
                  (when (< (length spin-var) 3)
                        (if (equal (length cur-var) 2)
                            (setf spin-var 
                                  (adjoin (select cur-var 1) spin-var)))))
            (when (= (length spin-var) 3)
                  (send sp :transformation nil :draw nil)
                  (send pp :current-variables 
                        (select spin-var 0) (select spin-var 1) )
                  (send pp :range 0 (first gnrpp) (second gnrpp) :draw nil)
                  (send pp :range 1 (first gnrpp) (second gnrpp) :draw nil)
                  (send pp :x-axis t t (third gnrpp) :draw nil)
                  (send pp :y-axis t t (third gnrpp) :draw nil)
                  (setf spin-var (reverse spin-var))
                  (send sp 
                        :current-variables (select spin-var 0)
                        (select spin-var 1) (select spin-var 2)
                        :draw nil)
                  (send sp :add-box) ;ng
                  ;(send sp :adjust-to-data)
                  (let ((cur-var (send sp :current-variables))
                        )
                    (send sp :set-variables-with-labels cur-var
                          (select (send sp :variable-labels) cur-var))
                    )
                  
                  (setf spin-var ())
                  )
            )
      ))

  (send sm :add-mouse-mode 'focus-on-variables
        :title "Focus On Variables"
        :click :do-variable-focus
        :cursor 'finger)

  (send sm  :mouse-mode 'focus-on-variables)
  sm)

(defmeth cmds-model :mds-3d-spin-plot (&optional (stream t))
  (setf *mds* self)
  (setf sp (spin-plot 
            (col (send self :xmatrix) 
                 (iseq (send self :number-dimensions)))
            :show nil
            :title "Stimulus Space"
            :variable-labels 
            (list "Dim1" "Dim2" "Dim3" "Dim4" "Dim5" "Dim6" "Dim7" "Dim8" "Dim9")
            :point-labels (send self :stimulus-names)
            :scale-type 'fixed))
  (let* ((h (+ (send sp :text-ascent)
               (send sp :text-descent))))
    )
  
  (send sp :scale-type 'centroid-fixed)
  (send sp :add-box) ;ok but ng for switched plots
  (send sp :switch-add-box)
  (send sp :point-symbol (iseq (send sp :num-points)) 'square)
  (send sp :point-color (iseq (send sp :num-points)) 'blue)
  (send sp :showing-labels t)
  (send sp :linked t)
  (send (first (send sp :slot-value 'overlays)) :install-button ':iterate)
  (send (first (send sp :slot-value 'overlays)) :install-button ':undo)
  (send (first (send sp :slot-value 'overlays)) :remove-button ':new-x)
  (send (first (send sp :slot-value 'overlays)) :remove-button ':new-y)
  (send (first (send sp :slot-value 'overlays)) :remove-button ':new-z)

  (defmeth sp :iter8 ()
    (let* ((n (array-dimension (send *mds* :xmatrix) 0))
           (m (array-dimension (send *mds* :xmatrix) 1)))
      (send current-model :prev-matrix (matrix (list n m)
              (copy-list (combine (send *mds* :xmatrix))))))
            
    (setf iter-number (get-value-dialog "How many iterations?"
                                        :initial 5))
    (dotimes (i (select iter-number 0))
             (let* ((n (array-dimension (send *mds* :xmatrix) 0))
                    (m (array-dimension (send *mds* :xmatrix) 1))
                    (trys (send stressp :num-points))
                    (old (matrix (list n m) 
                                 (copy-list (combine 
                                             (send *mds* :xmatrix)))))
                    (new (guttman-transform (send *mds* :xmatrix)))
                    (stress2 (calc-stress new 
                                          (send *mds*
                                                :transformed-data))))
               (send stressp :add-points 
                     (list (+ 1 trys)) (list stress2) :color 'red)
               (send stressp :add-lines-with-points :color 'red)
               (send stressp :point-label trys
                     (format nil "~5,4f" 
                             (send stressp :point-coordinate 1 trys)))
               (send stressp :point-state (- trys 1) 'normal)
               (send stressp :point-state trys 'selected)
               (send stressp :redraw)
               (send *mds* :stress stress2)
               (send *mds* :old-matrix old)
               (send *mds* :xmatrix new))
             (send *mds* :new-sm-points)
             (send *mds* :new-sp-points)
             (send *mds* :new-pp-points)
             ;(break)
             ))

  (defmeth sp :plot-help ()
    (plot-help-window (strcat "Help for " (send self :title)))
    (paste-plot-help (format nil "The STIMULUS SPACE window is a SpinPlot showing a 3-dimensional view of the stimulus space. The general details of how to use this plot are given below. There are several specific details for the multidimensional scaling SpinPlot that are mentioned first.~2%"))
(paste-plot-help (format nil "SPECIFIC MDS SPINPLOT HELP~2%"))
(paste-plot-help (format nil "The MDS SpinPlot has two special buttons at the top. These are the ITER and UNDO buttons. They both control the iterative process used to optimally locate the stimulus points.~2%"))
(paste-plot-help (format nil "ITER BUTTON~%When you click on the ITER button you will see a dialog window that lets you enter the maximum number of iterations to be performed. When you specify a number and click OK, the iterations will take place. You will see stimulus points move in the three windows that provide views of the stimulus space (SCATMAT, STIMULUS SPACE and STIMULUS PLANES), and you will see new Stress values added to the STRESS window.~2%"))
(paste-plot-help (format nil "UNDO BUTTON~%The UNDO button undoes iterations. There are three ways this button can be used.~%CLICK: If you simply click on it, the last group of iterations is undone (a group of iterations is the set of iterations that were performed the last time you used the ITER button).~%SHIFT-CLICK: If you shift-click on the button, all iterations are undone and the space is returned to its initial state.~%OPTION-CLICK: If you option-click on the button the last iteration is undone (this provides a way to rock back and forth between the last two iterations).~2%"))
(paste-plot-help (format nil "GENERAL SPINPLOT HELP~2%"))
    (show-plot-help)
    (call-next-method :flush nil)
    )

  (defmeth sp :undo-graph-change (m1 m2)
    (cond
      (m1 (send *mds* :back-to-start))
      (m2 (send *mds* :back-just-one))
      (t  (send *mds* :undo-iterations))))
    
      
  (defmeth sp :set-variables-with-labels (v labs)                                 
    (let ((n (send self :num-variables)))                                   
      (send self :variable-label (iseq n) (repeat "" n))             
      (send self :variable-label v labs)                                           
      (apply #'send self :current-variables v)
      ))
  sp)


(defmeth cmds-model :scree-plot () 
  (let ((n (length (send self :gamma)))
        (num-dim (send self :number-dimensions)))
    (setf scree-plot (plot-points (iseq 1 n) 
                                  (/ (send self :gamma)
                                     (sum (send self :gamma)))
                                  :show nil
                                  :title "Scree Plot"
                                  :variable-labels 
                                  (list "Dimensions" "Variance Proportion ")
                                  :scale nil))
    (send scree-plot :margin 0 17 0 0)
    (send scree-plot :add-overlay (send vista-graph-overlay-proto 
                               :new :mouse-mode nil :new-x nil :new-y nil))
    (send scree-plot :add-lines 
          (list (iseq 1 n) 
                (/ (send self :gamma)
                   (sum (send self :gamma)))) :draw nil :color 'red)
    (send scree-plot :point-color (iseq n) 'red)
    (let* ((prop (send scree-plot :point-coordinate 1 
                      (iseq (send scree-plot :num-points))))
           (maxy (first prop))
           (cum-prop (cumsum prop))) 
      (mapcar #'(lambda (i)
                  (send scree-plot :point-label i
                       (cond
                        ((> i 0) 
                         (format nil "~5,4f, ~5,4f, ~5,4f" 
                                 (select prop i) 
                                 (- (select prop (- i 1)) (select prop i) )
                                 (select cum-prop i)))
                         (t
                          (format nil "~5,4f" (select prop i))))))
              (iseq (send scree-plot :num-points)))
     ; (send scree-plot :point-label 0 (format nil "~5,4f" (select prop 0)))
      (send scree-plot :range 1 0  (* .1 (ceiling (* 10 maxy))) :draw nil)
      (send scree-plot :y-axis t t (1+   (ceiling (* 10 maxy))) :draw t))
   
    (send scree-plot :legend2 "Scree Plot")
    (send scree-plot :showing-labels t)
    (send scree-plot :mouse-mode 'brushing)
    (send scree-plot :menu nil)
    (send scree-plot :point-state (- num-dim 1) 'selected)
    (send scree-plot :adjust-to-data :draw nil)
    (send scree-plot :add-lines (repeat num-dim 2) 
          (list 0 (select (send scree-plot :range 1) 1))
          :type 'dashed)
    (defmeth scree-plot :plot-help ()
      (plot-help-window (strcat "Help for " (send self :title)))
      (paste-plot-help (format nil "The Scree plot shows the relative fit (importance) of each dimension. It does this by plotting the proportion of the data's variance that is fit by each dimension versus the dimension's number. The plot shows the relative importance of each dimension in fitting the data. It help you decide on the best dimensionality.~2%"))
      (paste-plot-help (format nil "The information in the scree plot is for the fit of the initial model, before iteration, to scalar products computed from the dissimilarity data (scalar products are also known as cross-products or outer-products). The fit is not recomputed after iterations occur. It still shows fit before the iterations. Fit is shown for the full set of possible dimensions, not just for the reduced set corresponding to the dimensionality you specified for the iterative analysis.~2%"))
      (paste-plot-help (format nil "The numbers beside the points provide information about the fit of each dimension. The first number is the proportion of the data's variance that is accounted for by the dimension. The second number is the difference in variance from the previous dimension. The third number is the total proportion of variance accounted for by the dimension and the preceeding dimensions.~2%"))
      (paste-plot-help (format nil "The Scree plot can be used to aid in the decision about how many dimensions are useful. You use it to make this decision by looking for an elbow (bend) in the curve. If there is one (and there often isn't) then the dimensions following the bend account for relatively little additional variance, and can perhaps be ignored.~2%"))
      (paste-plot-help (format nil "A dashed line is drawn on the plot at the dimensionality you specified. The Scree plot indicates, for this dimensionality, the details of the variance accounted for. You may move your cursor across other points in the plot for details about other dimensionalities. You should make sure that a sufficient proportion of the data's variance is accounted for by the specified dimensionality. The dashed line should be located just before an elbow of the curve.~2%"))
      (show-plot-help))
    scree-plot))

(defmeth cmds-model :name-plot (&optional (stream t))
  (setf np (name-list (send self :stimulus-names)
                      :show nil 
                      :title "Stimuli"
                      ))
  (send (send np :menu) :title "Stimuli")
  (send np :fix-name-list)
  (send np :linked t)
  np)


(defmeth cmds-model :use-new-point (i xvar yvar xscore yscore )
  (let* ((scores (list xscore yscore))
         (cur-vars (list xvar yvar))
         (new-matrix (send self :xmatrix))
         (n (array-dimension (send self :xmatrix) 0))
         (m (array-dimension (send self :xmatrix) 1))
         (copy-old (matrix (list n m) 
                           (copy-list (combine 
                                        (send self :xmatrix))))))
  (send self :old-matrix copy-old)
    (if (eq (send pp :mouse-mode) 'relocate-points)
        (setf k (select i 0))
        (setf k i))
    (send pp :point-coordinate xvar k xscore)
    (send pp :point-coordinate yvar k yscore)
    (send pp :redraw)
    
    (send sp :point-coordinate xvar k xscore)
    (send sp :point-coordinate yvar k yscore)
    (send sp :redraw)
    (send sm :point-coordinate xvar k xscore)
    (send sm :point-coordinate yvar k yscore)
    (send sm :redraw)
  (dotimes (j 2)
             (setf (aref new-matrix
                         k
                         (select cur-vars j))
                   (select scores j)))
    (send self :xmatrix new-matrix)
    (send stressp :add-points (list (+ 1 (send stressp :num-points)))
          (list (calc-stress new-matrix (send self :transformed-data)))
          :draw nil :color 'red)
    (send stressp :add-lines-with-points :color 'red)


    (send stressp :point-label (- (send stressp :num-points) 1)
          (format nil "~5,4f" 
                  (send stressp :point-coordinate 1 
                        (- (send stressp :num-points) 1))))
    (send stressp :add-lines-with-points :color 'red)
    (send stressp :point-state (- (send stressp :num-points) 2) 'normal)
    (send stressp :point-state (- (send stressp :num-points) 1) 'selected)

    (send stressp :redraw)))


(defmeth cmds-model :create-data 
  (&key (dialog nil)
        (coefs t)
        (input nil))
  (if (not (eq current-object self)) (setcm self))
  (let ((creator (send *desktop* :selected-icon))
        (desires (list (list (if coefs 0) (if input 1))))
        )
    (if dialog
        (setf desires
              (choose-subset-dialog "Choose Desired Data Objects"
                  '("Stimulus Coefficients (Coordinates)"
                    "Analyzed (Averaged) Input Data")
                    :initial (select desires 0))))
    (when desires
          (when (member '0 (select desires 0))
                (send self :mds-coefs-data-object  creator))
          (when (member '1 (select desires 0))
                (send self :mds-indata-data-object creator)))
    t));fwy 4.28 7/15/97 to make gm work right

(defmeth cmds-model :mds-coefs-data-object (creator)
  (data (concatenate 'string "Coefs-" (send self :name))
   :created creator
   :creator-object self
   :title (concatenate 'string "MDS Coefficients for " 
                       (send self :title))
   :data (combine (select (send self :xmatrix)
                          (iseq (length (send self :stimulus-names)))
                          (iseq (send self :number-dimensions))))
   :variables (mapcar #'(lambda (x) (format nil "Dim~a" x)) 
                      (iseq (send self :number-dimensions)))
   :labels (send self :stimulus-names)
   :types (repeat '"numeric" (send self :number-dimensions)))
  )

(defmeth cmds-model :mds-indata-data-object (creator)
  (data (concatenate 'string "Analyzed-" (send self :name))
   :created creator
   :creator-object self
   :matrices '("Analyzed Data")
   :title (concatenate 'string "Data analyzed by MDS from " 
                       (send self :title))
   :data (combine (send self :data))
   :variables (send self :stimulus-names)
   :labels (send self :stimulus-names))
  )
